
let {vec2,vec3,vec4,mat4} = require('gl-matrix');
let loader = require('./loader');
let objParser = require('./objParser');
let glExt = require('./glExt');
let shaderUtils = require('./shaderUtils');

//---------------------------------
// views
let canvas, gl;
let width, height;
let vao, posVBO,normalVBO,indiceVBO;
let shaderInfo;
let projMatrix = mat4.create();
let viewMatrix = mat4.create();
let worldMatrix = mat4.create();
let mvMatrix = mat4.create();
const fovy = 60;
const near = 0.1;
const far = 1000;
let indiceCount = 0;
let y = 0;

let scaleMat = mat4.create();
let posMat = mat4.create();
let rotMat = mat4.create();
const scale = 2;
mat4.fromScaling(scaleMat,vec3.fromValues(scale,scale,scale));
mat4.fromTranslation(posMat,vec3.fromValues(0,0,0));


let lastMs = Date.now();

window.onload = function () {
    console.log('----- window.onload');

    canvas = document.getElementById('game');
    width = canvas.width = canvas.clientWidth;
    height = canvas.height = canvas.clientHeight;
    gl = canvas.getContext('webgl');
    window.gl = gl;

    // 使用vao扩展
    glExt.useExt('OES_vertex_array_object');

    // init gl
    gl.enable(gl.DEPTH_TEST);
    gl.frontFace(gl.CCW);
    gl.cullFace(gl.BACK);
    gl.enable(gl.CULL_FACE);
    gl.clearColor(0,0,0,1);
    gl.viewport(0,0,width,height);


    // loadRes
    let vs = loader.loadText('assets/light.vs.glsl');
    let fs = loader.loadText('assets/light.fs.glsl');
    let monkey = loader.loadText('assets/ball.obj');
    Promise.all([vs,fs,monkey]).then(arr=>{

        let monkeyData = objParser.parse(arr[2]);

        shaderInfo = shaderUtils.buildShader(arr[0], arr[1]);
        shaderUtils.createUniforms(shaderInfo, ['projMatrix','viewMatrix',
            'mvMatrix','lightDir','ambientColor','dirLightIntensity','shiness']);
        shaderUtils.createAttribs(shaderInfo, ['a_position','a_normal']);


        // init matrixs
        mat4.perspective(projMatrix, fovy * Math.PI / 180, width / height, near, far);
        mat4.lookAt(viewMatrix, vec3.fromValues(0, 2, 5), vec3.create(), vec3.fromValues(0, 1, 0));

        vao = gl.createVertexArrayOES();
        gl.bindVertexArrayOES(vao);

        posVBO = gl.createBuffer();
        gl.bindBuffer(gl.ARRAY_BUFFER, posVBO);
        gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(monkeyData.positions), gl.STATIC_DRAW);
        gl.enableVertexAttribArray(shaderInfo.attribs['a_position']);
        gl.vertexAttribPointer(shaderInfo.attribs['a_position'], 3, gl.FLOAT, false, 0, 0);

        normalVBO = gl.createBuffer();
        gl.bindBuffer(gl.ARRAY_BUFFER,normalVBO);
        gl.bufferData(gl.ARRAY_BUFFER,new Float32Array(monkeyData.normals),gl.STATIC_DRAW);
        gl.enableVertexAttribArray(shaderInfo.attribs['a_normal']);
        gl.vertexAttribPointer(shaderInfo.attribs['a_normal'],3,gl.FLOAT,false,0,0);

        indiceVBO = gl.createBuffer();
        gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER,indiceVBO);
        gl.bufferData(gl.ELEMENT_ARRAY_BUFFER,new Uint16Array(monkeyData.indices),gl.STATIC_DRAW);
        indiceCount = monkeyData.indices.length;

        gl.bindVertexArrayOES(null);
        loop();
    });
};

function loop() {
    requestAnimationFrame(loop);

    let now = Date.now();
    let dtMs = now - lastMs;
    lastMs = now;
    // console.log('dt:',dtMs);

    y++;
    if (y > 360){
        y -= 360;
    }
    mat4.fromYRotation(rotMat,y * Math.PI / 180);
    mat4.copy(worldMatrix,posMat);
    mat4.mul(worldMatrix,worldMatrix,rotMat);
    mat4.mul(worldMatrix,worldMatrix,scaleMat);

    frame();

    let err = gl.getError();
    if (err){
        console.log('err:',err);
    }
}

function frame() {
    gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);

    gl.useProgram(shaderInfo.program);

    mat4.mul(mvMatrix, viewMatrix, worldMatrix);
    gl.uniformMatrix4fv(shaderInfo.uniforms['projMatrix'], false, projMatrix);
    gl.uniformMatrix4fv(shaderInfo.uniforms['mvMatrix'], false, mvMatrix);
    gl.uniform3f(shaderInfo.uniforms['ambientColor'],0.2,0.2,0.2);
    gl.uniform3f(shaderInfo.uniforms['lightDir'],1,1,0);
    gl.uniformMatrix4fv(shaderInfo.uniforms['viewMatrix'],false,viewMatrix);
    gl.uniform1f(shaderInfo.uniforms['dirLightIntensity'],0.6);
    gl.uniform1f(shaderInfo.uniforms['shiness'],32);
    gl.bindVertexArrayOES(vao);
    gl.drawElements(gl.TRIANGLES,indiceCount,gl.UNSIGNED_SHORT,0);

    gl.useProgram(null);
}



